package com.yiyihealth.cherriesadmin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.yiyihealth.cherriesadmin.core.http.HttpResult;
import com.yiyihealth.cherriesadmin.core.service.impl.BaseServiceImpl;
import com.yiyihealth.cherriesadmin.core.utils.JKTUtil;
import com.yiyihealth.cherriesadmin.mapper.*;
import com.yiyihealth.cherriesadmin.model.*;
import com.yiyihealth.cherriesadmin.model.his.DictPersonnel;
import com.yiyihealth.cherriesadmin.model.jkt.JThealth;
import com.yiyihealth.cherriesadmin.model.jkt.JktFunc10002;
import com.yiyihealth.cherriesadmin.model.jkt.JktFunc10003;
import com.yiyihealth.cherriesadmin.model.wrapper.PubDoctorWrapper;
import com.yiyihealth.cherriesadmin.service.PubDoctorService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.yiyihealth.cherriesadmin.core.utils.JKTUtil.sortMap;

/**
 * 医疗机构与人员信息关系表
 * (PubDoctor)表服务实现类
 *
 * @author chen
 * @since 2020-09-14 20:03:30
 */
@Service("pubDoctorService")
@CacheConfig(cacheNames = "doctor")
public class PubDoctorServiceImpl extends BaseServiceImpl<PubDoctor, PubDoctorWrapper, Long> implements PubDoctorService {
    @Resource
    private PubDoctorMapper pubDoctorMapper;
    @Resource
    private PubDepartmentsMapper pubDepartmentsMapper;
    @Resource
    private PubDictionaryMapper dictionaryMapper;
    @Resource
    private PubHospitalMapper hospitalMapper;
    @Resource
    private OrdSchedulingMapper schedulingMapper;

    @Resource
    private OrdSourceDetailMapper sourceDetailMapper;

    @Resource
    private JktFunc10003 jktFunc10003;
    @Resource
    private JThealth jThealth;

    @Resource
    private PubPatientsMapper patientsMapper;
    @Resource
    private RedisTemplate<Object, Object> redisCacheTemplate;


    @Autowired
    private void setEntityMapper() {
        super.setEntityMapper(pubDoctorMapper);
    }


    @Override
    public PubDoctorWrapper selectWrapperByPrimaryKey(Long aLong) {
        PubDoctorWrapper pubDoctorWrapper = pubDoctorMapper.selectWrapperByPrimaryKey(aLong);
        String redisKey = "departments:" + pubDoctorWrapper.getHospitalId() + ":" + pubDoctorWrapper.getDepId();
        PubDepartments pubDepartments = pubDepartmentsMapper.selectByPrimaryKey(pubDoctorWrapper.getDepId());
        redisCacheTemplate.opsForValue().set(redisKey, pubDepartments);
        pubDoctorWrapper.setDepNameWrapper(pubDepartments.getDepName());
        pubDoctorWrapper.setDoctorProfessionalWrapper(dictionaryMapper.selectWrapperByPrimaryKey(pubDoctorWrapper.getDoctorProfessional()).getDicName());
        return pubDoctorWrapper;
    }

    @Override
    public List<PubDoctorWrapper> selectListByDepId(@Param("DepId") Long DepId, @Param("status") String status, Long patId) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("depId", DepId);
        paramMap.put("status", 0);
        List<PubDoctorWrapper> doctorList = pubDoctorMapper.selectListWrapper(paramMap);
        PubPatients pubPatients = patientsMapper.selectByPrimaryKey(patId);
        HashMap<String, Object> docMap = new HashMap<>();
        docMap.clear();
        docMap.put("status", 0);
        docMap.put("depId", DepId);
        List<OrdScheduling> ordSchedulingList = schedulingMapper.selectList(docMap);
        for (OrdScheduling scheduling : ordSchedulingList) {
            PubDoctorWrapper pubDoctor = pubDoctorMapper.selectWrapperByPrimaryKey(scheduling.getDoctorId());
            if (!pubDoctor.getStatus().equals("0")) {
                continue;
            }
            List<PubDoctor> doctors = doctorList.stream().filter(pubDoctorWrapper -> pubDoctorWrapper.getId().toString().equals(pubDoctor.getId().toString())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(doctors)) {
                doctorList.add(pubDoctor);
            }
        }
        String vip = "0";
        doctorList = doctorList.stream().distinct().collect(Collectors.toList());
        Integer stopFlag= -2;
        for (PubDoctorWrapper doctor : doctorList) {
            if (doctor.getId().toString().equals("86000422")) {
                System.out.println(doctor);
            }
            //查询可预约排班 计算可预约排班总共剩余号数
            //这个*一定要加，否则无法模糊查询
            final String prefix = "scheduling:" + doctor.getId() + ":*";
            Set<Object> keys = redisCacheTemplate.keys(prefix);
            Integer amount = 0;
            //停诊标志
            stopFlag= -2;
            if (!Optional.ofNullable(keys).isPresent() || keys.size() == 0) {
                Map<String, Object> schedulingMap = new HashMap<String, Object>(8);
                schedulingMap.put("status", "0");
                schedulingMap.put("doctorId", doctor.getId());
                schedulingMap.put("hospitalId", doctor.getHospitalId());
                List<OrdScheduling> schedulingList = schedulingMapper.selectList(schedulingMap);
                if (!CollectionUtils.isEmpty(schedulingList)) {
                    for (OrdScheduling scheduling : schedulingList) {
                        Map<String, Object> sourceDetailMap = new HashMap<String, Object>(8);
                        sourceDetailMap.put("schedulingId", scheduling.getId());
                        sourceDetailMap.put("status", "0");
                        List<OrdSourceDetail> sourceDetailList = sourceDetailMapper.selectList(sourceDetailMap);
                        //设置过期时间
                        Duration duration = Duration.between(LocalDateTime.now(), scheduling.getSchedulingTime().atTime(23, 59, 59));
                        String schedulingKey = "scheduling:" + scheduling.getDoctorId() + ":" + scheduling.getId();
                        if (redisCacheTemplate.hasKey(schedulingKey)) {
                            redisCacheTemplate.delete(schedulingKey);
                        }
                        redisCacheTemplate.opsForValue().set(schedulingKey, scheduling.getAmount());
                        String sourceDetailKey = "sourceDetail:" + scheduling.getDoctorId() + ":" + scheduling.getId();
                        if (redisCacheTemplate.hasKey(sourceDetailKey)) {
                            redisCacheTemplate.delete(sourceDetailKey);
                        }
                        sourceDetailList.forEach(ordSourceDetail -> {
                            redisCacheTemplate.opsForSet().add(sourceDetailKey, ordSourceDetail.getId());
                        });
                        redisCacheTemplate.expire(sourceDetailKey, duration);
                    }
                }
                keys = redisCacheTemplate.keys(prefix);
            }
            for (Object key : keys) {
                Long schedulId = Long.valueOf(key.toString().split("\\:")[2]);
                OrdScheduling scheduling = schedulingMapper.selectByPrimaryKey(schedulId);
                if (!Optional.ofNullable(scheduling).isPresent()) {
                    continue;
                }
                if (LocalDate.now().isEqual(scheduling.getSchedulingTime())) {
                    continue;
                }
                if (scheduling.getStatus().equals("0")){
                    stopFlag= 1;
                }
                vip = "0";
                if (Optional.ofNullable(pubPatients).isPresent()) {
                    if (Optional.ofNullable(pubPatients.getPatMemGrade()).isPresent()) {
                        if (pubPatients.getPatMemGrade().equals("1")) {
                            vip = "1";
                            if (LocalDate.now().plusWeeks(2).isBefore(scheduling.getSchedulingTime())) {
                                continue;
                            }
                        } else {
                            if (LocalDate.now().plusWeeks(1).isBefore(scheduling.getSchedulingTime())) {
                                continue;
                            }
                            if (LocalDate.now().plusWeeks(1).isEqual(scheduling.getSchedulingTime())) {
                                if (LocalTime.now().isBefore(LocalTime.of(12, 0, 0))) {
                                    continue;
                                }
                            }
                        }
                    } else {
                        if (LocalDate.now().plusWeeks(1).isBefore(scheduling.getSchedulingTime())) {
                            continue;
                        }
                        if (LocalDate.now().plusWeeks(1).isEqual(scheduling.getSchedulingTime())) {
                            if (LocalTime.now().isBefore(LocalTime.of(12, 0, 0))) {
                                continue;
                            }
                        }
                    }
                } else {
                    //如果用户信息为空 则VIP号源不显示
                    if (scheduling.getDoctorPracticeScope().equals("2")) {
                        continue;
                    }
                    if (LocalDate.now().plusWeeks(1).isBefore(scheduling.getSchedulingTime())) {
                        continue;
                    }
                    if (LocalDate.now().plusWeeks(1).isEqual(scheduling.getSchedulingTime())) {
                        if (LocalTime.now().isBefore(LocalTime.of(12, 0, 0))) {
                            continue;
                        }
                    }
                }
                Map<String, Object> sourceDetailMap = new HashMap<String, Object>(8);
                sourceDetailMap.put("schedulingId", scheduling.getId());
                sourceDetailMap.put("status", "0");
                if (!vip.equals("1")) {
                    sourceDetailMap.put("type", "1");
                }
                List<OrdSourceDetail> sourceDetailList = sourceDetailMapper.selectList(sourceDetailMap);
                amount = amount + sourceDetailList.size();
            }
            String redisKey = "departments:" + doctor.getHospitalId() + ":" + doctor.getDepId();
            if (redisCacheTemplate.hasKey(redisKey)) {
                PubDepartments departments = (PubDepartments) redisCacheTemplate.opsForValue().get(redisKey);
                doctor.setDepNameWrapper(departments.getDepName());
            } else {
                PubDepartments pubDepartments = pubDepartmentsMapper.selectByPrimaryKey(doctor.getDepId());
                redisCacheTemplate.opsForValue().set(redisKey, pubDepartments);
                doctor.setDepNameWrapper(pubDepartments.getDepName());
            }

            //无排班
            if (!Optional.ofNullable(keys).isPresent() || keys.size() == 0){
                doctor.setAmount(-1);
            }else {
                if (stopFlag>0){
                    doctor.setAmount(amount);
                }else {
                    doctor.setAmount(stopFlag);
                }

            }
            doctor.setDoctorProfessionalWrapper(dictionaryMapper.selectWrapperByPrimaryKey(doctor.getDoctorProfessional()).getDicName());
        }
        return doctorList.stream().filter(pubDoctorWrapper -> pubDoctorWrapper.getStatus().equals("0")).collect(Collectors.toList());
    }

    /**
     * # 医院编码 57170-8063丰潭 57171-8064风起 57172-8065和平
     *
     * @throws Exception
     */
    @Scheduled(cron = "0 0 22 ? * *")
    @Override
    public synchronized void ExtractHisData() throws Exception {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("status", "0");
        List<PubHospital> hospitalList = hospitalMapper.selectList(paramMap);
        String tokenStr = "";
        String httpMsg;
        for (PubHospital hospital : hospitalList) {
            if (StrUtil.isBlank(hospital.getHosRegionalCode())) {
                continue;
            }
            tokenStr = "";
            httpMsg = "更新成功！";
            String json = JSONUtil.parseObj("{}").toString();
            try {
                tokenStr = HttpUtil.post(hospital.getHosRegionalCode() + "/dictPersonnel/select_list", json);
            } catch (Exception e) {
                httpMsg = "调用" + hospital.getHosName() + "中间数据处理服务失败,请确认服务地址：" + hospital.getHosRegionalCode() + "是否正常！";
            }
            paramMap.clear();
            paramMap.put("hospitalId", hospital.getId());
            List<PubDoctor> doctorList = pubDoctorMapper.selectList(paramMap);
            if (httpMsg.equals("更新成功！")) {
                HttpResult httpResult = JSONUtil.toBean(tokenStr, HttpResult.class);
                List<DictPersonnel> dictPersonnelList = JSONUtil.toList((JSONArray) httpResult.getData(), DictPersonnel.class);
                Integer num = 0;
                for (DictPersonnel dictPersonnel : dictPersonnelList) {
                    if (!hospital.getId().toString().equals(dictPersonnel.getHospitalId())) {
                        throw new Exception("中间服务地址错误，当前机构编码：" + hospital.getId() + " 请确认服务地址是否正确？");
                    }
                    num++;
                    System.out.println(num);
                    String redisKey = "doctor:" + dictPersonnel.getHospitalId() + ":" + dictPersonnel.getRenyuanbm();
                    if (hospital.getId().toString().equals("57171")) {
                        dictPersonnel.setRenyuanbm("D" + dictPersonnel.getRenyuanbm());
                    } else if (hospital.getId().toString().equals("57172")) {
                        dictPersonnel.setRenyuanbm("H" + dictPersonnel.getRenyuanbm());
                    }
                    String redisDepKey = "departments:" + dictPersonnel.getHospitalId() + ":" + dictPersonnel.getKeshibm();
                    if (!redisCacheTemplate.hasKey(redisDepKey)) {
                        continue;
                    }
                    PubDoctor doctor = new PubDoctor();
                    List<PubDoctor> doctorTempList = doctorList.stream()
                            .filter(pubDoctor -> pubDoctor.getHospitalId().toString().equals(dictPersonnel.getHospitalId()) && pubDoctor.getDoctorCode().equals(dictPersonnel.getRenyuanbm())).collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(doctorTempList)) {
                        doctor = createBean(dictPersonnel, doctor);
                        doctor.setUpdateStatus(httpMsg);
                        pubDoctorMapper.insert(doctor);
                    } else {
                        doctor = doctorTempList.get(0);
                        //判断是否同步数据
                        if (Optional.ofNullable(doctor.getSync()).isPresent() && doctor.getSync().equals("1")) {
                            doctorList.removeAll(doctorTempList);
                            continue;
                        }
                        doctor = createBean(dictPersonnel, doctor);
                        doctor.setUpdateStatus(httpMsg);
                        try {
                            pubDoctorMapper.updateByPrimaryKeySelective(doctor);
                        } catch (Exception e) {
                            throw new Exception("his端数据异常，请查证，人员编码" + dictPersonnel.getRenyuanbm() + dictPersonnel.getXingming() + "所在医馆编码：" + dictPersonnel.getHospitalId());
                        }
                    }
                    redisCacheTemplate.opsForValue().set(redisKey, doctor);
                    redisKey = "doctor:" + doctor.getHospitalId() + ":" + doctor.getId();
                    redisCacheTemplate.opsForValue().set(redisKey, doctor);
                    doctorList.removeAll(doctorTempList);
                }
                for (PubDoctor doctor : doctorList) {
                    doctor.setStatus("1");
                    pubDoctorMapper.updateByPrimaryKeySelective(doctor);
                }
            } else {
                for (PubDoctor doctor : doctorList) {
                    doctor.setUpdateStatus(httpMsg);
                    pubDoctorMapper.updateByPrimaryKeySelective(doctor);
                }
            }
        }
    }



    @Override
    public void jktUpload(Long hospitalId) throws Exception {
        Map<String, Object> map = new HashMap<>();
        if (!hospitalId.toString().equals("0")) {
            map.put("hospitalId", hospitalId);
        }
        List<PubDoctor> doctorList = pubDoctorMapper.selectList(map);
        for (PubDoctor doctor : doctorList) {
            try {
                PubDepartments departments = pubDepartmentsMapper.selectByPrimaryKey(doctor.getDepId());
                if (Optional.ofNullable(departments).isPresent()){

                    jktFunc10003.setDeptId(doctor.getDepId().toString());
                    jktFunc10003.setDeptName(departments.getDepName());

                    jktFunc10003.setDoctorId(doctor.getId().toString());
                    jktFunc10003.setDoctorName(doctor.getDoctorName());
                    jktFunc10003.setLevelCode(dictionaryMapper.selectByPrimaryKey(doctor.getDoctorProfessional()).getDicCode());
                    jktFunc10003.setDoctorDesc(doctor.getDoctorGoodat());
                    jktFunc10003.setHeaderUrl(doctor.getImageUrl()==null?"":jThealth.getServiceAddress()+"/"+doctor.getImageUrl());
                    jktFunc10003.setDoctorRemark(doctor.getDoctorGoodat());
                    if (doctor.getDoctorPracticeScope().equals("0")&&doctor.getStatus().equals("0")){
                        jktFunc10003.setDoctorState("0");
                    }else{
                        jktFunc10003.setDoctorState("1");
                    }
                    List<JSON> jktFun10003InList = new ArrayList<>();
                    sortMap(BeanUtil.beanToMap(jktFunc10003));
                    jktFun10003InList.add(JSONUtil.parse(jktFunc10003));
                    Map<String,Object> FuncMap =  new HashMap<>();
                    FuncMap.put("list",jktFun10003InList);
                    JKTUtil.jThealthPost("10003",FuncMap, jThealth);
                }
            }catch (Exception e){
                throw new Exception(e.getMessage());
            }
        }
    }

    PubDoctor createBean(DictPersonnel dictPersonnel, PubDoctor doctor) throws Exception {
        doctor.setDoctorName(dictPersonnel.getXingming());
        doctor.setDoctorSex(dictPersonnel.getXingbie());

        String redisKey = "departments:" + dictPersonnel.getHospitalId() + ":" + dictPersonnel.getKeshibm();
        if (redisCacheTemplate.hasKey(redisKey)) {
            PubDepartments departments = (PubDepartments) redisCacheTemplate.opsForValue().get(redisKey);
            doctor.setDepId(departments.getId());
        } else {
            throw new Exception(dictPersonnel.toString());
        }
        doctor.setDoctorCode(dictPersonnel.getRenyuanbm());
        if (Optional.ofNullable(dictPersonnel.getYbyszc()).isPresent()) {
            HashMap<String, Object> paramMap = new HashMap<>();
            if (dictPersonnel.getYbyszc() == null) {
                paramMap.put("dicCode", 5);
            } else {
                if (dictPersonnel.getYbyszc() < 0) {
                    paramMap.put("dicCode", 5);
                } else {
                    paramMap.put("dicCode", dictPersonnel.getYbyszc());
                }
            }

            List<PubDictionary> dictionaryList = new ArrayList<>();
            try {
                dictionaryList = dictionaryMapper.selectList(paramMap);
            } catch (Exception e) {
                throw new Exception("his端数据异常，请查证，人员编码" + dictPersonnel.getRenyuanbm() + dictPersonnel.getXingming() + "所在医馆编码：" + dictPersonnel.getHospitalId());
            }
            if (!CollectionUtils.isEmpty(dictionaryList)) {
                doctor.setDoctorDocGrade(dictionaryList.get(0).getId());
            } else {
                throw new Exception("his端数据异常，请查证，人员编码" + dictPersonnel.getRenyuanbm() + dictPersonnel.getXingming() + "所在医馆编码：" + dictPersonnel.getHospitalId());
            }
        } else {
            doctor.setDoctorDocGrade(3939L);
        }
        doctor.setStatus("0");
        if (!Optional.ofNullable(doctor.getDoctorProfessional()).isPresent()) {
            doctor.setDoctorProfessional(4430L);
        }
        if (StrUtil.isBlank(doctor.getDoctorGoodat())) {
            doctor.setDoctorGoodat("暂无");
        }
        if (StrUtil.isBlank(doctor.getDoctorSummary())) {
            doctor.setDoctorSummary("暂无");
        }
        doctor.setHospitalId(Long.valueOf(dictPersonnel.getHospitalId()));
        doctor.setStatus(dictPersonnel.getFengsuobz());
        doctor.setSync("0");
        //默认是全平台显示
        if (!Optional.ofNullable(doctor.getDoctorPracticeCode()).isPresent()) {
            doctor.setDoctorPracticeScope("0");
        }
        return doctor;
    }
}
